<?php

declare(strict_types=1);
/**
 * This file is part of habo_new_media.
 *
 * @link     https://www.berlen.cn/
 * @contact  tech@berlen.cn
 * @license  http://gitlab.rehou.cn/habo/habo_new_media/-/blob/master/README.md
 */
namespace app\service\batch\kuaishou;

use app\enum\BatchProjectEnum;
use app\enum\CommonEnum;
use app\enum\KuaiShouEnum;
use app\model\BatchProjectContentModel;
use app\model\FileUploadModel;
use app\model\KsUserVideoModel;
use app\model\mongo\MongoKsUserVideoModel;
use app\model\PushMaterialModel;
use app\model\VideoModel;
use app\service\batch\BatchService;
use app\service\client\AccountService;
use app\service\kuaishou\MaterialService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Env;

final class MaterialContentService extends BatchService
{
    public static function materialContent(BatchProjectContentModel $model): bool
    {
        try {
            if ($model->getAttr('content_level') != BatchProjectEnum::LEVEL_CREATIVE) {
                throw new Exception('创意层级错误');
            }
            $content = json_decode($model->getAttr('content'), true);
            if (empty($content['photo_ids']) && empty($content['pic_list']) && empty($content['image_tokens'])) {
                throw new Exception('素材获取失败');
            }
            $advertiserId = $model->getAttr('advertiser_id');
            $userId = strval(AccountService::getKsUserId($advertiserId));
            if (! $userId) {
                throw new Exception('获取user_id失败');
            }
            if (! empty($content['photo_ids'])) {
                foreach ($content['photo_ids'] as $photoId) {
                    if ($content['is_system'] == KuaiShouEnum::VIDEO_SOURCE_LOCAL) {
                        // 获取photoId
                        $photoId = self::getLocalPhotoId($photoId, $advertiserId, $userId);
                        if (! $photoId) {
                            throw new Exception('获取视频photo_id失败');
                        }
                    }
                    // 判断是否程序化+非智能抽帧
                    if ($content['creative_type'] == KuaiShouEnum::CREATIVE_TYPE_PROGRAM) {
                        // 获取视频信息
                        $video = (new MongoKsUserVideoModel())
                            ->where('user_id', $userId)
                            ->where('photo_id', strval($photoId))->find();
                        if (! $video) {
                            $video = (new KsUserVideoModel())
                                ->where('user_id', $userId)
                                ->where('photo_id', $photoId)->find();
                            if (! $video) {
                                throw new Exception('获取视频信息失败');
                            }
                        }
                        $content['photo_list'][] = [
                            'photo_id' => $photoId,
                            'cover_image_token' => $coverImage ?? '',
                            'creative_material_type' => $video['width'] < $video['height'] ? KuaiShouEnum::CREATIVE_MATERIAL_TYPE_VIDEO_VERTICAL : KuaiShouEnum::CREATIVE_MATERIAL_TYPE_VIDEO_HORIZONTAL,
                        ];
                    } else {
                        $content['photo_id'] = $photoId;
                    }
                }
                $model->setAttr('content', json_encode($content, JSON_UNESCAPED_UNICODE));
                $model->save();
            }
            // 入队列
            self::pushKsCreativeList($model->getKey());
            return true;
        } catch (\Exception $e) {
            $model->setAttr('status', BatchProjectEnum::PROJECT_STATUS_CONTENT_FALSE);
            $model->setAttr('error_msg', $e->getMessage());
            $model->save();
            // 设置搭建状态
            CreateProjectService::setProjectStatus($model->getAttr('project_id'));
            dump($e);
            return self::setError($e->getMessage());
        }
    }

    /**
     * 获取本地视频photoId.
     * @param int $id video表id
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private static function getLocalPhotoId(int $id = 0, string $advertiserId = '', string $userId = '')
    {
        $video = (new VideoModel())->find($id);
        if (! $video) {
            return self::setError('video表视频不存在');
        }
        // 判断是否已推送，如未推送，直接推送
        $photoId = MongoKsUserVideoModel::where('signature', $video['signature'])->where('user_id', $userId)->find();
        if ($photoId) {
            return $photoId['photo_id'];
        }
        // 获取同一userId下的账户是否推送过
        $photoId = PushMaterialModel::alias('a')
            ->join(['habo_ks_advertiser' => 'b'], 'a.advertiser_id=b.advertiser_id')
            ->where('a.file_id', $video['file_id'])
            ->where('b.user_id', $userId)
            ->value('photo_id');
        if ($photoId) {
            return $photoId;
        }
        $file = FileUploadModel::where('id', $video['file_id'])->find('file_url');
        if (! $file) {
            return self::setError('file_upload表信息不存在');
        }
        // 推送
        $fileLocal = Env::get('VIDEO_REAL_PATH') . $file->getAttr('file_url');
        if (! $fileLocal) {
            return self::setError('视频文件不存在');
        }
        $result = self::pushVideo($advertiserId, $fileLocal, $file->getAttr('file_name'));
        if (! $result) {
            return $result;
        }
        return $result['data']['photo_id'];
    }

    /**
     * 推送视频.
     * @param string $advertiserId 账户id
     * @param string $fileUrl 文件地址
     * @param string $fileName 文件名
     * @return bool|mixed|string
     */
    private static function pushVideo(string $advertiserId, string $fileUrl = '', string $fileName = '')
    {
        $token = AccountService::getToken(CommonEnum::KS_MEDIA, $advertiserId);
        if (! $token) {
            return self::setError('token获取失败');
        }
        $header = [
            'Access-Token' => $token,
            'Content-Type' => 'application/json',
            'K-RealUser-IP' => '',
        ];
        $params = [
            'advertiser_id' => $advertiserId,
            'file' => new \CURLFile($fileUrl),
            'signature' => md5_file($fileUrl),
            'photo_name' => $fileName,
            'shield_backward_switch' => false,
        ];
        return MaterialService::videoUpload($header, $params);
    }
}
